﻿using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text;

namespace Nextensions.WinApi
{
    public static class WindowHelper
    {
        public static IntPtr FindWindowRe(string WindowText)
        {
            IntPtr[] windows = FindWindowsRe(WindowText);

            if (windows.Length == 0)
                return IntPtr.Zero;

            return windows[0];
        }

        public static IntPtr[] FindWindowsRe(string WindowText)
        {
            WindowFinder wf = new WindowFinder();
            IntPtr[] windows = wf.FindRe(WindowText);

            return windows;
        }

        private static bool FindWindowProc(IntPtr Handle, int lParam)
        {
            return true;
        }

        public static void SetForegroundWindow(IntPtr Window)
        {
            Win.SetForegroundWindow(Window);
            Win.SetFocus(Window);
        }

        public static void ShowWindow(IntPtr Window)
        {
            Win.ShowWindow(Window, (int)ShowWindowCommand.SW_MAXIMIZE);
        }

        public static void SetCursorPos(Point Pos)
        {
            Win.SetCursorPos(Pos.X, Pos.Y);
        }

        public static Point GetCursorPos()
        {
            POINT pos;
            Win.GetCursorPos(out pos);
            return new Point(pos.X, pos.Y);
        }

        public static void SendMouseDoubleClick(Point Location)
        {
            SendMouseClick(Location);
            System.Threading.Thread.Sleep(150);
            SendMouseClick(Location);
        }

        public static void SendNaturalMouseClick(Point Location)
        {
            MouseMover mm = new MouseMover(Location, SendMouseClick);
        }

        public static void SendNaturalMouseDoubleClick(Point Location)
        {
            MouseMover mm = new MouseMover(Location, SendMouseDoubleClick);
        }

        public static void SendMouseClick(Point Location)
        {
            //throw new NotImplementedException("Randomize button click within bounds");
            //throw new NotImplementedException("Make mouse move naturally towards the button so that it sends a mouse over event");
            Win.SetCursorPos(Location.X, Location.Y);

            INPUT inputDown = new INPUT();
            inputDown.type = (uint)SendInputEventType.InputMouse;
            MouseInputData mi = new MouseInputData();
            mi.dx = Location.X;
            mi.dy = Location.Y;
            mi.mouseData = 0;
            mi.dwFlags = MouseEventFlags.MOUSEEVENTF_ABSOLUTE | MouseEventFlags.MOUSEEVENTF_LEFTDOWN;
            inputDown.mi = mi;

            System.Threading.Thread.Sleep(new Random().Next(400) + 25);

            INPUT inputUp = new INPUT();
            inputUp.type = (uint)SendInputEventType.InputMouse;
            mi = new MouseInputData();
            mi.dx = Location.X;
            mi.dy = Location.Y;
            mi.mouseData = 0;
            mi.dwFlags = MouseEventFlags.MOUSEEVENTF_ABSOLUTE | MouseEventFlags.MOUSEEVENTF_LEFTUP;
            inputUp.mi = mi;

            uint result;
            result = Win.SendInput(1, ref inputDown, Marshal.SizeOf(typeof(INPUT)));
            Win.SendInput(1, ref inputUp, Marshal.SizeOf(typeof(INPUT)));
        }

        public static Rectangle GetWindowRect(IntPtr hWndFtp)
        {
            RECT winRect;
            Win.GetWindowRect(hWndFtp, out winRect);

            return new Rectangle(winRect.Left, winRect.Top, winRect.Right - winRect.Left, winRect.Bottom - winRect.Top);
        }

        public static string GetWindowText(IntPtr Window)
        {
            StringBuilder text = new StringBuilder(256);
            Win.GetWindowText(Window, text, text.Capacity);
            return text.ToString();
        }

        public static IntPtr SetWindowHook(Win.HookProc Callback)
        {
            return Win.SetWindowsHookEx(HookType.WH_MOUSE_LL, Callback, IntPtr.Zero, 0);
        }

        public static bool BringWindowToTop(IntPtr Window)
        {
            return Win.BringWindowToTop(Window);
        }

        public static IntPtr WindowFromPoint(Point Point)
        {
            return Win.WindowFromPoint(new POINT(Point.X, Point.Y));
        }

        public static IntPtr SetWindowLongPtr(HandleRef hWnd, int nIndex, IntPtr dwNewLong)
        {
            if (IntPtr.Size == 8)
                return Win.SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
            else
                return new IntPtr(Win.SetWindowLong32(hWnd, nIndex, dwNewLong.ToInt32()));
        }
    }
}
